#include "predictor/TtsPredictor.h"

using namespace std;


vector<string> FrontAliVc::WriteBaseDictDb(const bool fcbInDeleteTable, const string fcInDictRootpath, const string fcOutDictRootpath)
{
	const vector< pair<string, string> > tcDictPaths = {
		{DatabaseDictTableZhTrand, fcInDictRootpath+"simplified/trand2simp.txt"},

		{DatabaseDictTableZhChar, fcInDictRootpath+"zh_dict/zh_word_base_phoneme.dict"},
		{DatabaseDictTableZhPhrase, fcInDictRootpath+"zh_dict/zh_phrase_base_phoneme.dict"},
		{DatabaseDictTableEnWord, fcInDictRootpath+"en_dict/en_word_base_phoneme.dict"},

		{DatabaseDictTableZhSymbol, fcInDictRootpath+"zh_symbol/zh_symbol.utf8"},
		{DatabaseDictTableEnSymbol, fcInDictRootpath+"en_symbol/en_symbol.utf8"}
	};

	vector<string> tResErrorLines;
	for(const pair<string, string> tPair: tcDictPaths) {
		vector<string> tTempErrorLines = gen_sqlite_dict(fcOutDictRootpath+"phoneme/phoneme.db", tPair.first, tPair.second, fcbInDeleteTable);
		tResErrorLines.insert(tResErrorLines.end(), tTempErrorLines.begin(), tTempErrorLines.end());
	}
	return tResErrorLines;
}


bool FrontAliVc::FrontInit(const string fcInDictRootpath, const string fcOutDictRootpath, const string fInModelPhonemeFilepath, const bool fInUpdateDictFlag)
{
	if(mFrontInst != nullptr) {
		return false;
	}

	//x86开发才用，android不用
	if(fInUpdateDictFlag) {
		ppspeech::DeleteVectorFiles(ppspeech::GetFolderFilenames(fcOutDictRootpath+"jieba/"), "cache");

		//ppspeech::DeleteVectorFiles(vector<string> {DatabaseDictPath}, "db");		const bool tcbDeleteTable = false;

		vector<string> tResErrorLines = WriteBaseDictDb(true, fcInDictRootpath, fcOutDictRootpath);
		cout << "基础字典错误行：" << tResErrorLines << endl;
	}

	// 实例化文本前端引擎
	mFrontInst = new ppspeech::FrontEngineInterface(fcOutDictRootpath, fcOutDictRootpath+"context/tts_user_context.txt", fInUpdateDictFlag);
	
	if( NULL == mFrontInst ) {
		return false;
	}

	if( false == mFrontInst->FrontEngineLoadPhonemeMap(fInModelPhonemeFilepath) ) {
		cout << "ERROR: Frontend: 加载TTS音素映射表失败！" << endl;
		if (mFrontInst != NULL) {
			delete mFrontInst;
			mFrontInst = NULL;
		}
		return false;
	}

	if( false == mFrontInst->FrontGetInitialedFlag() )
	{
		cout << "ERROR: Frontend: 初始化TTS前端引擎失败！" << endl;
		if (mFrontInst != NULL) {
			delete mFrontInst;
			mFrontInst = NULL;
		}
		return false;
	}
	cout << "文本分析：开始" << endl;
	return true;
}


void FrontAliVc::FrontDestroy()
{
	if(mFrontInst != nullptr) {
		delete mFrontInst;
		mFrontInst = nullptr;
	}
	cout << "文本分析：结束" << endl;
}


bool FrontAliVc::FrontProcess(const string& fcpInInputText, const string& fcpInputLanguage, vector< vector< vector<string> > >& fpOutSentenceAliVc)
{
	if(mFrontInst == nullptr) {
		return false;
	}

	wstring tWstrSentence = ppspeech::utf8string2wstring(fcpInInputText);

	// 繁体转简体
	wstring tWstrSimple;
	mFrontInst->TraditionalToSimplified(tWstrSentence, &tWstrSimple);
	tWstrSentence = tWstrSimple;


	fpOutSentenceAliVc.clear();

	// 设置句子语言
	mFrontInst->SetUseLanguage(&tWstrSentence, fcpInputLanguage);

	// 根据标点进行分句
	cout << "INFO: Frontend: 通过标点开始分段。" << endl;
	vector<wstring> tParts = mFrontInst->WstrSplitByPunctuation(tWstrSentence);
	cout << "INFO: Frontend: 完成标点分段。" << endl;

	// 分句后获取音素id
	cout << "INFO: Frontend: 开始获取每个句子的音素编号。" << endl;
	for (int i = 0; i < tParts.size(); i++) {
		cout << "INFO: Frontend: 原始句子是: " << ppspeech::wstring2utf8string(tParts[i]) << endl;
		mFrontInst->SentenceNormalize(&tParts[i]);

		string tSentence = ppspeech::wstring2utf8string(tParts[i]);
		cout << "INFO: Frontend: 正则化之后: " << tSentence << endl;

		vector< vector<string> > tPhonemes;
		if (false == mFrontInst->FrontGetSentencePhoneme(tSentence, &tPhonemes)) {
			cout << "ERROR: Frontend: 获取句子的音素失败！" << endl;
			return false;
		}
		
		fpOutSentenceAliVc.push_back(tPhonemes);
	}
	
	return true;
}
